<template>
  <vab-dialog v-model:modelValue="dialogVisible" destroyOnClose :title="`${dialogProps.title}`" :width="840">
    <div class="dig-box">
      <pro-table
        ref="proTableRef"
        :columns="columns"
        :data="tableData"
        default-expand-all
        :pagination="false"
        row-key="id"
        :tool-button="false"
        :tree-props="{ children: 'childrens' }"
        @select="select"
        @select-all="selectAll"
      >
        <template #operation="{ row }">
          <div>
            <el-checkbox
              v-for="(item, index) in row.dictList || []"
              :key="index"
              v-model="item.check"
              :label="item.id"
              @change="(ev) => onChangeBtn(ev as boolean, row)"
              @click.stop
            >
              {{ item.title }}
            </el-checkbox>
          </div>
        </template>
      </pro-table>
    </div>
    <template #footer>
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button v-show="!dialogProps.isView" type="primary" @click="handleSubmit">确定</el-button>
    </template>
  </vab-dialog>
</template>

<script setup lang="ts" name="RoleDialog">
import { ElMessage } from 'element-plus'
import { ref } from 'vue'
import { ColumnProps, ProTableInstance } from '~/library/components/ProTable/interface'
import { User } from '~/src/api/interface/user'

const proTableRef = ref<ProTableInstance>()
interface DialogProps {
  title: string
  isView: boolean
  id?: number
  api?: (params: any) => Promise<any>
  getTableList?: () => void
  row?: User.LoadMenuPageDict[]
}

const columns: ColumnProps<User.LoadMenuPageDict>[] = [
  { type: 'selection', width: 60 },
  { prop: 'title', label: '菜单名称', width: 200, align: 'left' },
  { prop: 'operation', label: '按钮权限', align: 'left' },
]
const tableData = ref<User.LoadMenuPageDict[]>([
  {
    check: true,
    childrens: [],
    component: '',
    dictList: [],
    id: 458,
    name: 'restaurant',
    page: null,
    parentId: 0,
    path: '/restaurant',
    redirect: '/restaurant/tableRms',
    sort: 1,
    title: '餐厅管理',
  },
])
const dialogVisible = ref(false)
const dialogProps = ref<DialogProps>({
  isView: false,
  title: '',
})
const defaultCheckedKeys = ref([])
const setSelection = (data: any) => {
  nextTick(() => {
    data.forEach((im: User.LoadMenuPageDict) => {
      if (im.check) {
        proTableRef.value?.element!.toggleRowSelection(im, true)
      }
      if (im.childrens.length > 0) {
        setSelection(im.childrens)
      }
    })
  })
}
const permissions = (list: any[], val: boolean) => {
  list.forEach((im) => {
    if (im.childrens.length === 0) {
      im.dictList.forEach((bts: any) => {
        bts.check = val
      })
    } else {
      permissions(im.childrens, val)
    }
  })
}
const onChangeBtn = (ev: boolean, row: any) => {
  if (ev) {
    proTableRef.value!.element!.toggleRowSelection(row, true)
  }
}

// 接收父组件传过来的参数
const acceptParams = async (params: DialogProps) => {
  dialogVisible.value = true
  dialogProps.value = params
  tableData.value = params.row as User.LoadMenuPageDict[]
  setSelection(tableData.value)
  defaultCheckedKeys.value = []
}

// 全选 反选
const selectAll = (selection: User.LoadMenuPageDict[]) => {
  // tabledata第一层只要有在selection里面就是全选
  const isSelect = selection.some((el: User.LoadMenuPageDict) => {
    const tableDataPaths = tableData.value.map((j: User.LoadMenuPageDict) => j.id)
    return tableDataPaths.includes(el.id)
  })
  // tableDate第一层只要有不在selection里面就是全不选
  const isCancel = !tableData.value.every((el: User.LoadMenuPageDict) => {
    const selectPaths = selection.map((j) => j.id)
    return selectPaths.includes(el.id)
  })
  if (isCancel) {
    tableData.value.map((el: User.LoadMenuPageDict) => {
      if (el.childrens) {
        // 解决子组件没有被勾选到
        setChildren(el.childrens, false)
      }
    })
  }
  if (isSelect) {
    selection.map((el) => {
      if (el.childrens) {
        // 解决子组件没有被勾选到
        setChildren(el.childrens, true)
      }
    })
  }
  if (selection.length > 0) {
    permissions(tableData.value, true)
  } else {
    permissions(tableData.value, false)
  }
}

// 设置父级选中/取消
const setParent = (currentRow: any, type: boolean, parent: User.LoadMenuPageDict[], selectionLists: User.LoadMenuPageDict[]) => {
  if (!parent.length) {
    parent = tableData.value
  }
  let allSelect: any[] = []
  parent.forEach((item: User.LoadMenuPageDict) => {
    if (item.childrens!.length > 0) {
      if (currentRow.parentId === item.id) {
        // 选中
        if (type) {
          selectionLists.forEach((k: User.LoadMenuPageDict) => {
            item.childrens?.forEach((j: User.LoadMenuPageDict) => {
              if (k.id == j.id) {
                allSelect.push(j)
              }
            })
          })
          if (allSelect.length == item.childrens?.length) {
            toggleSelection(item, type)
            selectionLists.push(item)
            select(selectionLists, item)
          } else {
            setParent(currentRow, type, item.childrens as [], selectionLists)
          }
        } else {
          // 取消选中
          toggleSelection(item, type)
          setParent(currentRow, type, item.childrens as [], [])
        }
      }
    }
  })
}

// 选中父节点时，子节点一起选中/取消
const select = (selection: User.LoadMenuPageDict[], row: User.LoadMenuPageDict) => {
  const hasSelect = selection.some((el: User.LoadMenuPageDict) => {
    return row.id === el.id
  })
  if (hasSelect) {
    if (row.childrens!.length > 0) {
      // 解决子组件没有被勾选到
      setChildren(row.childrens as [], true)
    }
    // 子节点被全勾选，父节点也勾上
    setParent(row, true, [], selection)
  } else {
    if (row.childrens!.length > 0) {
      setChildren(row.childrens as [], false)
    }
    // 子级取消选中, 传入当前选中节点, 所有父级取消选中
    setParent(row, false, [], [])
  }
}

const setChildren = (children: User.LoadMenuPageDict[], type: boolean) => {
  // 编辑多个子层级
  children.map((j: User.LoadMenuPageDict) => {
    toggleSelection(j, type)
    if (j.childrens) {
      setChildren(j.childrens, type)
    }
  })
}

const toggleSelection = (row: User.LoadMenuPageDict, select: boolean) => {
  // 编辑多个子层级
  if (row) {
    proTableRef.value?.element!.toggleRowSelection(row, select)
  }
}

const flattenTree = (data: User.LoadMenuPageDict[]) => {
  let newData: any[] = []
  const callback = (item: any) => {
    ;(item.childrens || (item.childrens = [])).map((v: any) => {
      callback(v)
    })
    delete item.childrens
    newData.push(item)
  }
  data.map((v) => callback(v))
  function removeDuplicatesById(items: any[]): any[] {
    return items.filter((item, index) => {
      const foundIndex = items.findIndex((other) => other.id === item.id)
      return foundIndex === index
    })
  }
  newData = removeDuplicatesById(newData)
  return newData
}

// 提交数据（新增/编辑）
const handleSubmit = async () => {
  try {
    await dialogProps.value.api!({ id: dialogProps.value.id, data: flattenTree(proTableRef.value!.selectedList as []) })
    ElMessage.success({ message: `设置成功！` })
    dialogVisible.value = false
  } catch (error) {
    console.log(error)
  }
}

defineExpose({
  acceptParams,
})
</script>
<style lang="scss" scoped>
.dig-box {
  height: 560px;
  overflow: scroll;
}
</style>
